home *** CD-ROM | disk | FTP | other *** search
- /*
- Programs.c - support routines for manipulating the CD Remote Programs
- file.
- ©Apple Computer, Inc. 1988
- All Rights Reserved.
- */
-
- #include "cd.h"
- #include "SysEqu.h"
-
- typedef struct {
- unsigned long index;
- short rsrcID;
- } entryStruct;
-
-
-
-
- /************************************************************************
- *
- * Function: OpenSystemResFile
- *
- * Purpose: open a resource file that's in the system folder
- *
- * Returns: whatever would be returned by OpenResFile()
- * -1 indicates an error. You must call ResError()
- * to find the real error.
- * Any other value is the refNum for that resource file.
- *
- * Side Effects: opens the specified file.
- *
- * Description: Save the current volume. Get the volume of the
- * system folder. Set that as the default volume.
- * Open the file. Restore all the settings.
- *
- ************************************************************************/
- int
- OpenSystemResFile(fileName)
- Str255 *fileName;
- {
- int curVol;
- OSErr result;
- SysEnvRec theWorld;
-
- GetVol(nil, &curVol);
-
- result = SysEnvirons(curSysEnvVers, &theWorld);
- if (result == noErr)
- {
- SetVol(nil, theWorld.sysVRefNum);
-
- result = OpenResFile(fileName);
-
- SetVol(nil, curVol);
- }
-
- return result;
- }
-
-
- /************************************************************************
- *
- * Function: FindIndex
- *
- * Purpose: find a resource ID, given an index
- *
- * Returns: boolean
- * true if the index existed
- * false if no such index. This means we've never
- * seen this disc before.
- *
- * Side Effects: fills in rsrcID.
- *
- * Description: the IndX resource contains 8 bytes of header,
- * followed by an array of 6 byte entries.
- *
- * The first two bytes of the header are the
- * version of this resource, and will be 0x0010
- * or 0x0011. Don't check--it will change someday.
- * The next two bytes are the number of entries.
- *
- * In the entries, the first byte is the number of
- * tracks on the disc. The next three bytes are the
- * index we're trying to match. The last two bytes
- * are the resource ID of both the 'STR#' resource
- * and the 'ProG' resource (telling the desk
- * accessory in what order to play the tracks).
- * Fill in rsrcID with that number, if found.
- *
- *
- ************************************************************************/
- Boolean
- FindIndex(index, rsrcID)
- unsigned long index;
- short *rsrcID;
- {
- short numEntries;
- entryStruct *entryPtr;
- short *headerPtr;
- Boolean foundIt;
- Handle indexHandle;
-
- foundIt = false;
- *rsrcID = 0;
-
- indexHandle = Get1Resource('IndX', 128);
- if (indexHandle == nil)
- return false;
-
- HLock(indexHandle);
- headerPtr = (short *) *indexHandle;
-
- headerPtr++;
- numEntries = *headerPtr++;
- entryPtr = (entryStruct *)headerPtr;
-
- while (numEntries > 0 & foundIt == false)
- {
- if ((entryPtr->index & 0x00FFFFFF) == index)
- {
- *rsrcID = entryPtr->rsrcID;
- foundIt = true;
- }
- entryPtr++;
- numEntries--;
- }
-
- HUnlock(indexHandle);
-
- ReleaseResource(indexHandle);
- return (foundIt);
- }
-
- /************************************************************************
- *
- * Function: AddDisc
- *
- * Purpose: add a CD to the CD Remote Programs file
- *
- * Returns: OSErr
- * noErr if everything went well.
- * something else whatever was returned by the call
- * that gave us the error.
- *
- * Side Effects: Adds an IndX entry and a ProG and STR# resource
- * to the file 'CD Remote Programs'
- *
- * Description: Get the IndX resource #128 (famous value).
- * Get a new resource number, using Unique1ID. Get
- * a handle for the new IndX resource. (It will be six
- * bytes greater than the current one, since that's
- * the size of an IndX entry.) The entry contains
- * the number of tracks (byte)
- * the total number of blocks on disc (3 bytes)
- * unique resource ID we just got (2 bytes)
- * Store that away. Get enough room for the ProG
- * resource (2 bytes per track, plus 2 byte header).
- * Initialize that to default value (we don't yet
- * support Program playing.) The ID of this ProG is
- * equal to our unique ID.
- * For the STR#, build a default using the STR
- * resources for the words 'Volume title' and
- * 'Track N'. Build the STR# and add it, of ID equal
- * to our unique ID.
- *
- *
- ************************************************************************/
- OSErr
- AddDisc(discID, numberOfTracks)
- unsigned long discID;
- short numberOfTracks;
- {
- OSErr result;
- short uniqueID; /* for ProG and STR# IDs */
-
- result = noErr;
-
- if (result == noErr)
- result = AddIndX(discID, numberOfTracks, &uniqueID);
-
- if (result == noErr)
- result = AddTitles(uniqueID, numberOfTracks);
-
- if (result == noErr)
- result = AddProG(uniqueID, numberOfTracks);
-
- return result;
- }
-
-
- /************************************************************************
- *
- * Function: AddIndX
- *
- * Purpose: Add a new IndX entry
- *
- * Returns: OSErr
- * noErr, unless somebody we call goes bad.
- *
- * Side Effects: size of IndX resource 128 grows by 6 bytes
- *
- * Description: Get the 'IndX' resource number 128. Figure out the
- * size of resource. Allocate a handle of that size
- * plus six bytes (1 byte number of tracks, 3 bytes
- * disk id, 2 bytes resource number). Copy from the
- * original resource to the new one.
- *
- ************************************************************************/
- OSErr
- AddIndX(discID, numTracks, uniqueID)
- unsigned long discID;
- short numTracks; /* number of tracks on this disc. */
- short *uniqueID;
- {
- Handle indxHandle;
- short unique;
- Size indxSize;
- entryStruct *indexPtr;
- OSErr result;
- short *headerPtr;
- unsigned long newIndex;
- short numEntries;
-
-
- indxHandle = nil;
- result = noErr;
-
- indxHandle = Get1Resource('IndX', 128);
-
- if (indxHandle == nil)
- result = ResError();
-
- if (result == noErr)
- {
- do {
- unique = Unique1ID('ProG');
- } while (unique < 128); /* don't want system rsrc ID. see IM I-121 */
- }
-
- if (result == noErr)
- {
- indxSize = GetHandleSize(indxHandle) + 6;
- SetHandleSize(indxHandle, indxSize);
- result = MemError();
- }
- HLock(indxHandle);
- headerPtr = (short *) *indxHandle;
-
- if (result == noErr)
- {
- headerPtr++; /* skip version number */
- numEntries = *headerPtr;
- *headerPtr = numEntries+1;
- headerPtr++;
- indexPtr = (entryStruct *)headerPtr;
-
- newIndex = (discID & 0x00FFFFFF) | ((long)numTracks << 24);
- indexPtr[numEntries].index = newIndex;
- indexPtr[numEntries].rsrcID = unique;
- *uniqueID = unique;
- }
- HUnlock(indxHandle);
-
- if (result == noErr)
- {
- ChangedResource(indxHandle);
- result = ResError();
- }
- if (result == noErr)
- {
- WriteResource(indxHandle);
- result = ResError();
- }
-
- ReleaseResource(indxHandle);
- return result;
- }
-
-
- /************************************************************************
- *
- * Function: AddProG
- *
- * Purpose: Add a new ProG resource for a CD
- *
- * Returns: OSErr
- * usually noErr, but could have problems creating
- * the new ProG resource.
- *
- * Side Effects: Modifies "CD Remote Programs" file to add new
- * resource.
- *
- * Description: A 'ProG' resource is made as follows:
- * 1) a word giving the number of tracks on this disc
- * in hexadecimal.
- * 2) a two-byte entry for each track, containing
- * i) a byte indicating whether to play this track
- * or not (1 = play, 0 = not)
- * ii) a byte containing the track number in BCD.
- * We create such a default ProG resource for the disc
- * in question.
- *
- ************************************************************************/
- OSErr
- AddProG(rsrcID, numTracks)
- short rsrcID;
- short numTracks;
- {
- Handle progHandle;
- Handle resHandle;
- OSErr result;
- Size progSize;
- short *progPtr;
- short i;
-
- result = noErr;
- progSize = (numTracks * 2) + 2; /* 2 bytes per track + header */
-
- progHandle = NewHandle(progSize);
- if (progHandle == nil)
- result = MemError();
-
- HLock(progHandle);
-
- if (result == noErr)
- {
- progPtr = (short *) *progHandle;
- progPtr[0] = numTracks;
- for (i = 1; i <= numTracks; i++)
- progPtr[i] = (short) DECIMAL2BCD(i) | 0x0100;
- }
-
- HUnlock(progHandle);
- if (result == noErr)
- {
- AddResource(progHandle, 'ProG', rsrcID, "\p");
- result = ResError();
- }
- if (result == noErr)
- {
- resHandle = GetResource('ProG', rsrcID);
- WriteResource(resHandle);
- result = ResError();
- ReleaseResource(resHandle);
- }
-
- return result;
- }
-
- /************************************************************************
- *
- * Function: AddTitles
- *
- * Purpose: add default song titles for this disc
- *
- * Returns: OSErr
- * usually noErr, but could have problems creating
- * the new STR# resource.
- *
- * Side Effects: Modifies "CD Remote Programs" file to add new
- * resource.
- *
- * Description: A 'STR#' resource consists of a two byte value which
- * is the number of strings, followed by the strings.
- * Each string is a pascal string (i.e. with a length
- * byte preceeding it.) We generated such a resource
- * by getting a Handle for the header, and using
- * Munger (IM I-468) to add the strings.
- *
- ************************************************************************/
- OSErr
- AddTitles(rsrcID, numTracks)
- short rsrcID;
- short numTracks;
- {
- Handle stringHandle;
- Handle resHandle;
- OSErr result;
- Size stringSize;
- short *stringPtr;
- short i;
- short mungerReturn;
- Str255 trackName;
- char trackNumber[3]; /* 01 - 99 inclusive */
- Str31 discTitle;
- Str31 trackTitle;
-
- result = noErr;
- stringSize = 2; /* 2 byte header containing number of strings */
-
- GetIndString(discTitle, STR_ID, DISKTITLE);
- if (discTitle == (Str31)0)
- result = ResError();
-
- GetIndString(trackTitle, STR_ID, TRACKTITLE);
- if (trackTitle == (Str31)0)
- result = ResError();
- p2cstr(trackTitle);
-
- if (result == noErr)
- {
- stringHandle = NewHandle(stringSize);
- if (stringHandle == nil)
- result = MemError();
- }
-
- if (result == noErr)
- {
- HLock(stringHandle);
- stringPtr = (short *) *stringHandle;
- stringPtr[0] = numTracks+1; /* add title, too */
- HUnlock(stringHandle);
- mungerReturn = Munger(stringHandle, GetHandleSize(stringHandle),
- "\p", 0L, discTitle, 11L);
- for (i = 1; i <= numTracks; i++)
- {
- strcpy(trackName, trackTitle);
- ltoa((long) i, trackNumber);
- strcat(trackName, trackNumber);
- c2pstr(trackName);
- mungerReturn = Munger(stringHandle, GetHandleSize(stringHandle),
- "\p", 0L, trackName, trackName[0]+1);
- }
- }
-
- if (result == noErr)
- {
- AddResource(stringHandle, 'STR#', rsrcID, "\p");
- result = ResError();
- }
- if (result == noErr)
- {
- resHandle = GetResource('STR#', rsrcID);
- WriteResource(resHandle);
- result = ResError();
- ReleaseResource(resHandle);
- }
-
- return result;
- }
-
-
- /************************************************************************
- *
- * Function: GetNumberTracks
- *
- * Purpose: report how many tracks are on this CD
- *
- * Returns: OSErr. Probably either
- * noErr everything's hunky-dory!
- * paramErr you messed up the call somehow.
- *
- * Side Effects: none
- *
- * Description: Simply call the driver.
- *
- ************************************************************************/
- OSErr
- GetNumberTracks(refNum, numberTracks)
- short refNum;
- short *numberTracks;
- {
- CDParam myPB;
- OSErr result;
-
- myPB.ioCompletion = 0;
- myPB.ioNamePtr = (char *) 0;
- myPB.ioVRefNum = 1;
- myPB.ioCRefNum = refNum;
- myPB.csCode = READTOC;
- myPB.csParam[0] = 0;
- myPB.csParam[1] = 1;
-
- result = PBControl(&myPB, false);
-
- if (result == noErr)
- *numberTracks = (short) BCD2DECIMAL(myPB.csParam[1]);
- return result;
- }
-
-
- /************************************************************************
- *
- * Function: IDDisc
- *
- * Purpose: return total time on this disc as unique ID
- *
- * Returns: OSErr
- * either noErr if everything was okay
- * or some parameter error from driver call.
- *
- * Side Effects:
- * fills in discID
- *
- * Description:
- * call the driver ReadTOC call to get lead-out time.
- * Return this time as the unique id for this disc.
- *
- ************************************************************************/
- OSErr
- IDDisc(refNum, discID)
- short refNum;
- unsigned long *discID;
- {
- CDIDParam myPB;
- OSErr result;
-
- myPB.ioCompletion = 0;
- myPB.ioNamePtr = (char *) 0;
- myPB.ioVRefNum = 1;
- myPB.ioCRefNum = refNum;
- myPB.csCode = READTOC;
- myPB.discID = 0x00020000; /* request lead-out time */
-
- result = PBControl((ParmBlkPtr)&myPB, false);
-
- if (result == noErr)
- *discID = myPB.discID >> 8;
- else
- *discID = 0;
- return result;
- }
-
-
- /************************************************************************
- *
- * Function: HandleToPString
- *
- * Purpose: copy contents of handle to pascal string
- *
- * Returns: void
- *
- * Side Effects: pointer p's contents are made those of handle h
- *
- * Description: We assume that you've allocated space large enough
- * to store the contents.
- *
- ************************************************************************/
- void
- HandleToPString(h, p)
- Handle h;
- Ptr p;
- {
- strcpy(p, *h);
- c2pstr(p);
- }
-
-